package main

import (
	"fmt"
	"time"

	"github.com/go-xorm/xorm"
	"github.com/google/uuid"
)

// StartStatsService 启动统计服务（每小时执行一次统计）
func StartStatsService(engine *xorm.Engine) {
	// 立即执行一次统计（启动时统计历史数据）
	DoStats(engine)

	// 定时任务：每小时执行一次
	ticker := time.NewTicker(1 * time.Hour)
	defer ticker.Stop()

	fmt.Println("统计服务启动，每小时执行一次统计")
	for range ticker.C {
		DoStats(engine)
	}
}

// DoStats 执行统计逻辑（PV+框架分布+UA分布）
func DoStats(engine *xorm.Engine) {
	startTime := time.Now()
	fmt.Printf("开始统计，时间：%s\n", startTime.Format("2006-01-02 15:04:05"))

	// 统计时间粒度：取当前小时的起始时间（如14:00:00）
	statTime := time.Date(startTime.Year(), startTime.Month(), startTime.Day(), startTime.Hour(), 0, 0, 0, startTime.Location())

	// 1. 统计PV（当前小时的总访问量）
	if err := statsPV(engine, statTime); err != nil {
		fmt.Printf("PV统计失败: %v\n", err)
	}

	// 2. 统计框架分布（当前小时各框架的访问次数）
	if err := statsFramework(engine, statTime); err != nil {
		fmt.Printf("框架统计失败: %v\n", err)
	}

	// 3. 统计UA分布（当前小时各UA的访问次数）
	if err := statsUA(engine, statTime); err != nil {
		fmt.Printf("UA统计失败: %v\n", err)
	}

	fmt.Printf("统计完成，耗时%v\n", time.Since(startTime))
}

// statsPV 统计PV（按小时）
func statsPV(engine *xorm.Engine, statTime time.Time) error {
	// 统计当前小时内的日志总数
	count, err := engine.Where("access_time >= ? and access_time < ?",
		statTime, statTime.Add(1*time.Hour)).Count(new(TrafficLog))
	if err != nil {
		return err
	}

	// 先删除该时间维度的旧统计（避免重复统计）
	_, err = engine.Where("stat_time = ? and stat_type = ?", statTime, "pv").Delete(new(TrafficStat))
	if err != nil {
		return err
	}

	// 插入新统计结果
	stat := TrafficStat{
		Id:        uuid.NewString(),
		StatTime:  statTime,
		StatType:  "pv",
		StatKey:   "total",
		StatValue: int(count),
	}
	_, err = engine.Insert(stat)
	return err
}

// statsFramework 统计框架分布
func statsFramework(engine *xorm.Engine, statTime time.Time) error {
	// 按框架分组统计当前小时的访问次数
	type FrameworkCount struct {
		Framework string `xorm:"varchar(50)"`
		Count     int    `xorm:"int"`
	}
	var frameworkCounts []FrameworkCount

	err := engine.Table("traffic_logs").
		Select("framework, count(*) as count").
		Where("access_time >= ? and access_time < ?", statTime, statTime.Add(1*time.Hour)).
		GroupBy("framework").
		Find(&frameworkCounts)
	if err != nil {
		return err
	}

	// 先删除该时间维度的旧框架统计
	_, err = engine.Where("stat_time = ? and stat_type = ?", statTime, "framework").Delete(new(TrafficStat))
	if err != nil {
		return err
	}

	// 批量插入新统计结果
	var stats []TrafficStat
	for _, fc := range frameworkCounts {
		stats = append(stats, TrafficStat{
			Id:        uuid.NewString(),
			StatTime:  statTime,
			StatType:  "framework",
			StatKey:   fc.Framework,
			StatValue: fc.Count,
		})
	}
	_, err = engine.Insert(&stats)
	return err
}

// statsUA 统计UA分布
func statsUA(engine *xorm.Engine, statTime time.Time) error {
	// 按UA分组统计当前小时的访问次数
	type UACount struct {
		UserAgent string `xorm:"varchar(255)"`
		Count     int    `xorm:"int"`
	}
	var uaCounts []UACount

	err := engine.Table("traffic_logs").
		Select("user_agent, count(*) as count").
		Where("access_time >= ? and access_time < ?", statTime, statTime.Add(1*time.Hour)).
		GroupBy("user_agent").
		Find(&uaCounts)
	if err != nil {
		return err
	}

	// 先删除该时间维度的旧UA统计
	_, err = engine.Where("stat_time = ? and stat_type = ?", statTime, "ua").Delete(new(TrafficStat))
	if err != nil {
		return err
	}

	// 批量插入新统计结果
	var stats []TrafficStat
	for _, uc := range uaCounts {
		stats = append(stats, TrafficStat{
			Id:        uuid.NewString(),
			StatTime:  statTime,
			StatType:  "ua",
			StatKey:   uc.UserAgent,
			StatValue: uc.Count,
		})
	}
	_, err = engine.Insert(&stats)
	return err
}
